home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Online / SpeakFreely / CONTRIB / xspeakfree-0.7 / lib / xspeakfree / cmd.tcl < prev    next >
Text File  |  2000-05-16  |  10KB  |  379 lines

  1. proc GetOS {} {
  2.     set os {unknown-unix}
  3.     catch {set os [exec {uname}]}
  4.     return $os
  5. }
  6.  
  7. proc timestr {} {
  8.     return [clock format [clock seconds] -format {%m-%d %I:%M %p}]
  9. }
  10.  
  11. proc Exit {} {
  12.     ControlSpeaker close
  13.     ControlMike close
  14.     exit 0
  15. }
  16.  
  17. proc Speaker_readevent {} {
  18.     global Speaker
  19.  
  20.     if [eof $Speaker(exec:stdout)] {
  21.         GUI_print "[timestr]: ERROR: sfspeaker shutdown"
  22.         ControlSpeaker close
  23.     } else {
  24.         gets $Speaker(exec:stdout) line
  25.  
  26.         if [regexp {([^ ]+) connect$} $line a host] {
  27.             set host [string tolower $host]
  28.             GUI_hostlist add $host -comment {sfspeaker stream} -connection true -transmit true
  29.             GUI_print "[timestr]: $host connected."
  30.             set Speaker(pri:in:$host:protocol) {}
  31.             set Speaker(pri:in:$host:compression) {}
  32.             return
  33.         }
  34.         if [regexp {([^ ]+) sending in (.+)$} $line a host proto] {
  35.             set host [string tolower $host]
  36.             set Speaker(pri:in:$host:protocol) [lreplace $proto end end]
  37.             return
  38.         }
  39.         if [regexp {([^ ]+) sending ([^ ]+) compressed\.$} $line a host compression] {
  40.             set host [string tolower $host]
  41.             set Speaker(pri:in:$host:compression) $compression
  42.             GUI_print "[timestr]: $host sending audio ($Speaker(pri:in:$host:compression)/$Speaker(pri:in:$host:protocol))."
  43.             return
  44.         }
  45.         if { ([regexp {connection closed} $line] && [regexp {sfspeaker: ([^ ]+) } $line a host]) ||
  46.             ([regexp {([^ ]+) idle$} $line a host])} {
  47.             set host [string tolower $host]
  48.  
  49.             set done 0
  50.             foreach n [array names Speaker "pri:in:$host:*"] {
  51.                 set done 1
  52.                 catch "unset Speaker($n)"
  53.             }
  54.             if {$done == 1} {
  55.                 GUI_hostlist edit $host -transmit false
  56.                 GUI_print "[timestr]: $host disconnected."
  57.             }
  58.             return
  59.         }
  60.         if {![string first { sending from } $line]} {
  61.             GUI_print "  -- ERROR: sfspeaker:  [string trimleft $line]"
  62.         }
  63.     }
  64. }
  65.  
  66. proc ControlSpeaker { cmd {spio {}} } {
  67.     global Speaker
  68.  
  69.     if {$cmd == {restart}} { set cmd {open} }
  70.  
  71.     if {$Speaker(exec:id) != {} && ($cmd == {open} || $cmd == {close})} {
  72.         close_exec $Speaker(exec:id)
  73.         set Speaker(exec:id) {}
  74.     }
  75.  
  76.     if {$cmd == {open}} {
  77.         set Speaker(exec:id) [open_exec -command "sfspeaker -v -p$Speaker(port) $Speaker(args)" -stdout Speaker(exec:stdout)]
  78.         fileevent $Speaker(exec:stdout) readable Speaker_readevent
  79.     }
  80. }
  81.  
  82. proc Mike_readevent {} {
  83.     global Mike
  84.  
  85.     if [eof $Mike(exec:stdout)] {
  86.         GUI_print "[timestr]: ERROR: sfmike shutdown"
  87.         ControlMike close
  88.     } else {
  89.         if {[gets $Mike(exec:stdout) line] == -1} {
  90.             set line [read $Mike(exec:stdout)]
  91.         }
  92.         if {[string first "Space bar switches" $line] != -1} {
  93.             GUI_print "[timestr]: ready to broadcast to $Mike(target)."
  94.             set Mike(:state:text) "Ready"
  95.             set Mike(pri:ready) 1
  96.             if {$Mike(:state) == 1} {
  97.                 set Mike(:state) 0
  98.                 ControlMike on
  99.             }
  100.             return
  101.         }
  102.         if {[string first "Pause" $line] != -1} {
  103.             set Mike(:state) 0
  104.             set Mike(:state:text) "Ready"
  105.             return
  106.         }
  107.         if {[string first "Talk" $line] != -1} {
  108.             set Mike(:state) 1
  109.             set Mike(:state:text) "Sending"
  110.             return
  111.         }
  112.         if {$line != {} && $line != "\x0A\x09 \x0A"} {
  113.             GUI_print "  -- ERROR: sfmike:  [string trimleft $line]"
  114.         }
  115.     }
  116. }
  117.  
  118. proc ControlMike { cmd } {
  119.     global Mike
  120.  
  121.     if {$cmd == {toggleProc}} {
  122.         if {$Mike(exec:id) == {}} { set cmd {open} } else { set cmd {close} }
  123.     }
  124.     if {$cmd == {restart}} { set cmd {open} }
  125.  
  126.     if {$Mike(exec:id) != {} && ($cmd == {close} || $cmd == {open})} {
  127.         close_exec $Mike(exec:id)
  128.  
  129.         set Mike(exec:id) {}
  130.  
  131.         if {$cmd == {close}} {
  132.             GUI_set_menu_item_state connection close disabled
  133.  
  134.             set Mike(target) {}
  135.             set Mike(:state) 0
  136.             set Mike(:state:text) "Off"
  137.             set Mike(:button) "Mute"
  138.             set Mike(pri:ready) 0
  139.         }
  140.     }
  141.     if {$cmd == {open} && $Mike(target) != {}} {
  142.         if {$Mike(connect:send_ring) == 1 && $Mike(:state) == 0} {
  143.             set ring [GetSoundPath ring]
  144.             GUI_print "[timestr]: sending ring sound to $Mike(target)."
  145.         } else {
  146.             set ring {}
  147.         }
  148.  
  149.         set Mike(exec:id) [open_exec -command "sfmike $Mike(args) $Mike(target) $ring ." -stdin Mike(exec:stdin) -stdout Mike(exec:stdout)]
  150.         fconfigure $Mike(exec:stdout) -blocking false
  151.         fileevent $Mike(exec:stdout) readable Mike_readevent
  152.         set Mike(pri:ready) 0
  153.  
  154.         GUI_set_menu_item_state connection close normal
  155.     }
  156.     if {$Mike(exec:id) != {} && $cmd == {on} && $Mike(pri:ready) == 1} {
  157.         if {$Mike(:state) != 1} {
  158.             puts -nonewline $Mike(exec:stdin) { }
  159.             flush $Mike(exec:stdin)
  160.         }
  161.     }
  162.     if {$Mike(exec:id) != {} && $cmd == {off}} {
  163.         if {$Mike(:state) != 0} {
  164.             puts -nonewline $Mike(exec:stdin) { }
  165.             flush $Mike(exec:stdin)
  166.         }
  167.     }
  168. }
  169.  
  170. proc ModifyArgs {item} {
  171.     upvar #0 $item i
  172.     
  173.     set i(args) {}
  174.     foreach {n v} [array get i {args:*}] {
  175.         if {[regexp {:eval$} $n]} {
  176.             eval $v
  177.         } else {
  178.             append i(args) { } $v
  179.         }
  180.     }
  181.     if {$i(exec:id) != {}} { $i(command) restart }
  182. }
  183.  
  184. proc GetSoundPath {file} {
  185.     global env SoundFile DataDir LibDir
  186.  
  187.     if {[array get SoundFile $file] != {}} {
  188.         set file $SoundFile($file)
  189.     }
  190.  
  191.     foreach path [list $file [file join $env(HOME) $file] [file join $DataDir $file] [file join $LibDir $file] ] {
  192.  
  193.         if {[file exists $path]} { return $path }
  194.     }
  195.     
  196.     return {}
  197. }
  198.  
  199. proc SendSoundFile_readevent {id stdout host snd} {
  200.     if [eof $stdout] {
  201.         close_exec $id
  202.  
  203.         # remove sound file name from list
  204.         set n [GUI_hostlist get $host -sound]
  205.         set x [string first $snd $n]
  206.         if {$x != -1} {
  207.             set y [string range $n 0 [expr $x - 1]]
  208.             append y [string range $n [expr $x + [string length $snd] + 2] end]
  209.             GUI_hostlist edit $host -sound [string trimright $y {; }]
  210.         }
  211.  
  212.         # remove execid from list
  213.         regsub "$id ?" [GUI_hostlist varget $host {sendsnd:exec}] {} n
  214.         GUI_hostlist varset $host {sendsnd:exec} $n
  215.     } else {
  216.         set line [read $stdout]
  217.     }
  218. }
  219.  
  220. proc SendSoundFile { host file {noprint {}} } {
  221.     set path [GetSoundPath $file]
  222.     if {$path == {}} { return 0 }
  223.     if {$noprint == {}} {
  224.         GUI_print "[timestr]: sending $file to $host."
  225.     }
  226.     if {$host == {localhost}} {
  227.         set c {-N}
  228.     } else {
  229.         set c {-T}
  230.     }
  231.  
  232.     GUI_hostlist edit $host -sound [string trimright "[file tail $path]; [GUI_hostlist get $host -sound]" { ;}]
  233.     set id [open_exec -command "sfmike $host $c $path" -stdout stdout]
  234.     fconfigure $stdout -blocking false
  235.     fileevent $stdout readable "SendSoundFile_readevent $id $stdout $host [file tail $path]"
  236.     GUI_hostlist varset $host {sendsnd:exec} "[GUI_hostlist varget $host {sendsnd:exec}]$id "
  237.     return 1
  238. }
  239.  
  240. proc InitProcess {} {
  241.     global Speaker SoundFile Mike HostListConstants env
  242.  
  243.     set SoundFile(busy) {busy.au}
  244.     set SoundFile(ring) {ring.au}
  245.  
  246.     set Speaker(exec:id) {}
  247.     set Speaker(port) 2074
  248.     set Speaker(args) {}
  249.     set Speaker(args:jitter) { }
  250.     set Speaker(args:disable_remote_ring) { }
  251.     set Speaker(args:user) {}
  252.     set Speaker(command) ControlSpeaker
  253.     set Speaker(:record:file) "$env(HOME)/sfspeaker_audio.next"
  254.     set Speaker(:record:append) {}
  255.     set Speaker(:record:onoff) 0
  256.  
  257.     set Speaker(args:record:eval) {
  258.         if {$i(:record:onoff) == 1 && $i(:record:file) != {}} {
  259.             append i(args) " -R$i(:record:append)$i(:record:file)"
  260.         } else {
  261.             set i(:record:onoff) 0
  262.         }
  263.     }
  264.     set Speaker(:crypt:method) { }
  265.     set Speaker(args:crypt:eval) {
  266.         global Speaker
  267.         if {$Speaker(:crypt:method) != { }} {
  268.             append i(args) "$Speaker(:crypt:method)$Speaker(:crypt:$Speaker(:crypt:method))"
  269.         }
  270.     }
  271.     set Mike(args:crypt:eval) $Speaker(args:crypt:eval)
  272.  
  273.     set Mike(exec:id) {}
  274.     set Mike(target) {}
  275.     set Mike(args) {}
  276.     set Mike(command) ControlMike
  277.     set Mike(args:simplecompression) { }
  278.     set Mike(args:compression) {-T}
  279.     set Mike(args:protocol) { }
  280.     set Mike(args:user) {}
  281.     set Mike(args:ring) { }
  282.  
  283.     set Mike(connect:send_ring) 0
  284.     
  285.     set Mike(hostlist:add:send_busy) 0
  286.     set Mike(hostlist:add:play_ring) 0
  287.  
  288.     set Mike(:state) 0
  289.     set Mike(:state:text) {Off}
  290.     set Mike(:button) {Mute}
  291.  
  292.     set HostListConstants [list]
  293. }
  294.  
  295. set xspeakfree_rc_path "$env(HOME)/.xspeakfree.rc"
  296. set xspeakfree_hostlist_path  "$env(HOME)/.xspeakfree.hostlist"
  297.  
  298. #Handle command line args
  299. for {set llen [llength $argv]; set i 0} {$i < $llen} {incr i} {
  300.     switch -glob -- [lindex $argv $i] {
  301.         -[fF]* { regexp -nocase -- {-f(.*)} [lindex $argv $i] a xspeakfree_rc_path }
  302.         -[pP]* { regexp -nocase -- {-p(.*)} [lindex $argv $i] a Speaker(port) }
  303.         -[nN] { set Speaker(args:disable_remote_ring) {-n} }
  304.         -? -
  305.         -[uU] -
  306.         default {
  307.             puts {usage: xspeakfree [-n][-p<port>][-f<path>]
  308.  
  309.     -f<path>    use different xspeakfree.rc than
  310.                 $HOME/.xspeakfree.rc
  311.     -n        disable remote ring
  312.     -p<port>    force sfspeaker to listen on port number <port>
  313.     -u        this help message
  314. }
  315.             exit
  316.         }
  317.     }
  318. }
  319.  
  320. InitProcess
  321. GUI_draw
  322. GUI_help_about
  323.  
  324. # source siteconf.tcl
  325. source [file join $LibDir siteconf.tcl]
  326.  
  327. # Load user's .xspeakfree.rc
  328. if [catch { source $xspeakfree_rc_path } error] {
  329.     if {$error != "couldn't read file \"$xspeakfree_rc_path\": no such file or directory"} {
  330.         GUI_print "ERROR: in $xspeakfree_rc_path"
  331.         GUI_print "    " $error
  332.         GUI_print "--------------------------"
  333.     } else {
  334.         GUI_print "Could not load $xspeakfree_rc_path"
  335.     }
  336. } else {
  337.     GUI_print "$xspeakfree_rc_path loaded"
  338. }
  339. unset error
  340. unset xspeakfree_rc_path
  341.  
  342. # Load user's .xspeakfree.hostlist
  343. if {[catch {set fd [open $xspeakfree_hostlist_path {r}]} error]} {
  344.     if {[catch {set fd [open $xspeakfree_hostlist_path {w}]} error]} {
  345.         GUI_print "Could not create $xspeakfree_hostlist_path: $error"
  346.     } else {
  347.         puts $fd "# xspeakfree host list
  348. # this file contains the default values for the target host list popup
  349. # its format is IP or DNS name of the host followed by whitespace and then
  350. # a comment field that lasts until the end of the line.
  351. # ie:
  352. # echo.fourmilab.ch    Echo Server
  353. #
  354. "
  355.         foreach {n l} $HostList_Defaults {
  356.             puts $fd "$n    $l"
  357.             lappend HostListConstants $n $l
  358.             GUI_hostlist add $n -comment $l
  359.         }
  360.         close $fd
  361.         GUI_print "Created $xspeakfree_hostlist_path"
  362.     }
  363. } else {
  364.     while {[gets $fd line] > -1} {
  365.         if {![regexp {^#} $line] && [string length $line] > 1} {
  366.             lappend HostListConstants [lindex $line 0] [lrange $line 1 end]
  367.             GUI_hostlist add [lindex $line 0] -comment [lrange $line 1 end]
  368.         }
  369.     }
  370.     close $fd
  371.     GUI_print "$xspeakfree_hostlist_path loaded"
  372. }
  373. unset xspeakfree_hostlist_path
  374. unset error
  375.  
  376. ModifyArgs Speaker
  377. ModifyArgs Mike
  378. ControlSpeaker open
  379.